/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * This file is part of retabel.
 *
 * Copyright (c) 2011 by individual contributors as indicated by the
 * @author tags. See the copyright.txt file in the distribution
 * for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.retabel.web.rest;

import org.apache.http.HttpStatus;
import org.retabel.persistence.entity.report.RenderingEngineEnum;
import org.retabel.persistence.entity.report.ReportDesign;
import org.retabel.service.manager.ReportDesignPackageManager;
import xsd.reportdesignpackage.ReportDesignPackage;
import xsd.reportdesignpackages.ObjectFactory;
import xsd.reportdesignpackages.ReportDesignPackageList;
import xsd.reportdesignpackages.ReportDesignPackages;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

/**
 * Report design REST interface implementation
 * <p/>
 * <h3>Extra-Info</h3>
 * Created: 10:19 16.07.11
 *
 * @author Burt Parkers, Peter Herber
 * @version 1.0
 */
@Path("/designs/")
@Stateless
public class ReportDesignPackageServiceBean extends RestServiceBean {

    // constants

    @EJB
    private ReportDesignPackageManager reportDesignPackageManager;

    @POST
    @Consumes("application/zip")
    @Produces(MediaType.TEXT_PLAIN)
    public Response postReportDesign(@QueryParam("archiveName") String archiveName, @QueryParam("version") String version,
                                     @QueryParam("renderingEngine") String renderEngineParamValue, byte[] bytes,
                                     @Context UriInfo uriInfo) {
        PlainTextResponseBuilder response = new PlainTextResponseBuilder(uriInfo);

        response.println("Attempting to store report design ...");
        response.println("archiveName: " + archiveName);
        response.println("version: " + version);
        response.println("renderEngineParamValue: " + renderEngineParamValue);

        RenderingEngineEnum renderingEngine = RenderingEngineEnum.valueOf(renderEngineParamValue);

        if (renderingEngine == null) {
            return Response.status(HttpStatus.SC_BAD_REQUEST).entity(
                "not supported value encountered for parameter renderingEngine: " + renderEngineParamValue).build();
        }

        try {
            response.println("archiveData: [" + bytes.length + "]");

            reportDesignPackageManager.store(renderingEngine, archiveName, version, bytes);
        } catch (Exception e) {
            response.println(e.toString());

            return response.getServerErrorResponse();
        }

        return response.getResponse();
    }

    @GET
    @Produces(MediaType.TEXT_XML)
    public Response getReportDesignPackages(@QueryParam("first") Integer first,
                                            @QueryParam("maxRows") Integer maxRows) {
        int maxRowsWithFallback = maxRows != null ? maxRows : getDefaultMaxResultsPerPage();
        int firstWithFallback = first != null ? first : 0;

        int countReportDesigns = reportDesignPackageManager.count();

        org.retabel.persistence.entity.report.ReportDesignPackage[] reportDesignPackages = reportDesignPackageManager
            .findAllSorted(firstWithFallback, maxRowsWithFallback);

        ObjectFactory of = new ObjectFactory();

        ReportDesignPackages result = of.createReportDesignPackages();
        result.setStart(firstWithFallback);
        result.setRows(reportDesignPackages.length);
        result.setCount(countReportDesigns);

        ReportDesignPackageList reportDesignList = of.createReportDesignPackageList();
        result.setList(reportDesignList);

        for (org.retabel.persistence.entity.report.ReportDesignPackage reportDesignPackage : reportDesignPackages) {
            xsd.reportdesignpackages.ReportDesignPackage resultReportDesignPackage = of.createReportDesignPackage();
            resultReportDesignPackage.setName(reportDesignPackage.getName());
            resultReportDesignPackage.setVersion(reportDesignPackage.getVersion());

            reportDesignList.getReportDesignPackage().add(resultReportDesignPackage);
        }

        return Response.ok(result).build();
    }

    @GET
    @Path("/{name}/{version}")
    @Produces(MediaType.TEXT_XML)
    public Response getReportDesignPackage(@PathParam("name") String name,
                                           @PathParam("version") String version) {
        org.retabel.persistence.entity.report.ReportDesignPackage reportDesignPackage =
            reportDesignPackageManager.findByNameAndVersion(name, version);
        
        if (reportDesignPackage == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        xsd.reportdesignpackage.ObjectFactory of = new xsd.reportdesignpackage.ObjectFactory();

        ReportDesignPackage xmlReportDesignPackage = of.createReportDesignPackage();
        xmlReportDesignPackage.setName(reportDesignPackage.getName());
        xmlReportDesignPackage.setVersion(version);

        for (ReportDesign reportDesign : reportDesignPackage.getReportDesigns()) {
            xsd.reportdesignpackage.ReportDesign xmlReportDesign = of.createReportDesign();
            xmlReportDesign.setName(reportDesign.getName());

            xmlReportDesignPackage.getReportDesign().add(xmlReportDesign);
        }

        return Response.ok(xmlReportDesignPackage).build();
    }

    /**
     * Download the file within the specified design package
     *
     * @param name the name of the design package the design relies to
     * @param version the version of the design package the design relies to
     * @param designName the design to be downloaded, may contain slashes in order to handle package sub directories
     *
     * @return the byte contents as octet stream or 404 if not found
     */
    @GET
    @Path("/{name}/{version}/{designName:.+}")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response getReportDesign(@PathParam("name") String name, @PathParam("version") String version,
                                    @PathParam("designName") String designName) {
        org.retabel.persistence.entity.report.ReportDesignPackage reportDesignPackage =
            reportDesignPackageManager.findByNameAndVersion(name, version);

        if (reportDesignPackage == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        ReportDesign reportDesign = reportDesignPackage.getReportDesignByName(designName);

        if (reportDesign == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.ok(reportDesign.getContent()).build();
    }

    @DELETE
    @Path("/{name}/{version}")
    @Produces(MediaType.TEXT_PLAIN)
    public Response delete(@PathParam("name") String name, @PathParam("version") String version, @Context UriInfo uriInfo) {
        PlainTextResponseBuilder response = new PlainTextResponseBuilder(uriInfo);

        response.println("Deleting report design package: " + name + " [" + version + "]");

        reportDesignPackageManager.remove(name, version);

        return response.getResponse();
    }

}
